
using System.Collections.Generic;
using System.Timers;
using AudioStudio;
using GameFramework.Battle.Core;
using Gameplay.PVE.Config;
using Gameplay.PVE.Entity;
using Gameplay.PVE.Utils;
using UnityEngine;

namespace Gameplay.PVE.Skill
{
    public class SkillMelee : SkillBase
    {
        private float startShootTime;
        private float startBulletTime;
        private Dictionary<int,List<BulletData>> bullets;
        private int shootCount;
        private List<Vector2> frameSpeedChangeList;
        private int currentFrameSpeedChangeIndex;
        private float frameSpeedChangeValue = 0.05f;
        private float frameSpeedChangeDuration = 0.1f;
        private float frameSpeedRevertTime;
        
        protected override void Cast()
        {
            //if (targetUnit == null)
            {
                targetUnit = unit.Data.lockTarget;
                if (unit.Data.lockTarget == null)
                {
                    StartRecover();
                    return;
                }
                targetPosition = unit.Data.lockTarget.Data.position;
            }
            lastLockTarget = targetUnit;
            bulletCount = 0;
            shootCount = 0;
            Shoot();
        }

        protected override void Storage()
        {
            base.Storage();
            unit.Data.SetIsCanMove(false);
            if (string.IsNullOrEmpty(config.storage_name))
            {
                unit.Play("AttackStart");
            }
            else
            {
                unit.Play(config.storage_name);
            }
            stateStartTime = currentTime;
            storageTime = config.storage_time / unit.Data.attackSpeedRatio;
            if (bullets == null)
            {
                bullets = new Dictionary<int, List<BulletData>>();
                for (int i = 0; i < config.bullets.Count; i++)
                {
                    int key = (int) config.bullets[i].z;
                    if (!bullets.ContainsKey(key))
                    {
                        bullets.Add(key,new List<BulletData>());
                    }
                    bullets[key].Add(new BulletData
                    {
                        bulletConfig = config.bullets[i],
                    });
                }
            }

            currentFrameSpeedChangeIndex = 0;
            if (frameSpeedChangeList == null)
            {
                frameSpeedChangeList = new List<Vector2>();
                for (int i = 0; i < config.bullets.Count; i++)
                {
                    frameSpeedChangeList.Add(new Vector2((config.bullets[i].x+1) / 30f,frameSpeedChangeValue));
                }
            }
            //Debug.LogError(PveManager.frame + "\t" + unit.Data.id + " 近战攻击开始");
        }
        
        protected override void Recover()
        {
            base.Recover();
            unit.Data.SetIsInAttack(false);
            unit.Data.SetIsCanMove(true);
        }

        protected override void OnStop()
        {
            base.OnStop();
            unit.Data.SetIsInAttack(false);
            unit.Data.SetIsCanMove(true);
        }

        protected override void StartRecover()
        {
            //if (CheckHasAmmo())
            {
                lastLockTarget = null;
                recoverTime = config.attack_recover_time / unit.Data.attackSpeedRatio;
                base.StartRecover();
                if (string.IsNullOrEmpty(config.recover_name))
                {
                    unit.Play("AttackEnd",1);
                }
                else
                {
                    unit.Play(config.recover_name,1);
                }
                this.State = ESkillState.Recover;
                stateStartTime = currentTime;
            }
            /*else
            {
                state = ESkillState.None;
                unit.Data.SetIsInAttack(false);
                unit.Data.SetIsCanMove(true);
                unit.Transmit(ETransmitType.Reload);
            }*/

            unit.Transmit(ETransmitType.AttackEnd);
        }

        protected override bool CheckIsCanSkill()
        {
            return base.CheckIsCanSkill();// && unit.Data.IsInAttack() && unit.Data.IsCanAttack();
        }

        protected override bool CastEndCondition()
        {
            return false;
        }

        protected override void Reset()
        {
            bullets?.Clear();
            bullets = null;
            frameSpeedChangeList?.Clear();
            frameSpeedChangeList = null;
            base.Reset();
        }

        protected override void CastEvent()
        {
            if (unit.Data.isDead)
            {
                return;
            }

            var timeScale = 1f;
            var actionTime = currentTime - startShootTime;
            if (frameSpeedRevertTime > 0 && actionTime >= frameSpeedRevertTime)
            {
                timeScale = 1;
                frameSpeedRevertTime = 0;
                this.timeScale = timeScale;
            }
            else
            {
                for (int i = currentFrameSpeedChangeIndex; i < frameSpeedChangeList.Count; i++)
                {
                    if (frameSpeedChangeList[i].x <= actionTime)
                    {
                        timeScale = frameSpeedChangeList[i].y;
                        currentFrameSpeedChangeIndex = i + 1;
                        frameSpeedRevertTime = actionTime +
                                               frameSpeedChangeDuration * frameSpeedChangeValue;
                        this.timeScale = timeScale;
                        break;
                    }
                }
            }
            
            if (unit.Data.skillFrameSpeedChangeValue != this.timeScale)
            {
                for (int i = 0; i < effectList.Count; i++)
                {
                    var controller = effectList[i].effectController;
                    if (controller != null)
                    {
                        controller.SetSpeed(this.timeScale);
                    }
                }
            }
            unit.Data.skillFrameSpeedChangeValue = this.timeScale;
            if (!unit.Data.IsAttackInRange(1f))
            {
                this.timeScale = 1;
                unit.Data.skillFrameSpeedChangeValue = 1;
                StartRecover();
                RemoveEffect();
                return;
            }
            
            if (startShootTime != 0 && actionTime >= config.attack_cast_time / unit.Data.attackSpeedRatio)
            {
                if (shootCount >= unit.Data.shootTurns)
                {
                    StartRecover();
                    return;
                }
                else
                {
                    foreach (var item in bullets)
                    {
                        for (int i = 0; i < item.Value.Count; i++)
                        {
                            if (item.Value[i].startTime > 0 && currentTime >= item.Value[i].startTime)
                            {
                                Bullet(item.Value[i].bulletConfig,item.Value[i].effectConfig);
                                item.Value[i].startTime = item.Value[i].startTime + config.attack_cast_time;
                            }
                        }
                
                    }
                    Shoot();
                    startShootTime = currentTime;
                }
            }
            
            foreach (var item in bullets)
            {
                for (int i = 0; i < item.Value.Count; i++)
                {
                    if (item.Value[i].startTime > 0 && currentTime >= item.Value[i].startTime)
                    {
                        Bullet(item.Value[i].bulletConfig,item.Value[i].effectConfig);
                        item.Value[i].startTime = item.Value[i].startTime + config.attack_cast_time;
                    }
                }
                
            }

            if (unit.Data.lockTarget != null)
            {
                targetPosition = unit.Data.lockTarget.Data.position;
                targetForward = targetPosition - unit.Data.position;
                unit.Data.SetTargetForward(targetForward);
            }
           
        }

        private UnitBase lastLockTarget;
        
        protected virtual void Shoot()
        {
            if (unit.Data.lockTarget != lastLockTarget)
            {
                /*if (unit.Data.lockTarget != null && unit.Data.IsAttackInRange(1))
                {
                    lastLockTarget = unit.Data.lockTarget;
                    targetPosition = unit.Data.lockTarget.Data.position;
                    targetForward = targetPosition - unit.Data.position;
                    unit.Data.SetTargetForward(targetForward);
                    unit.Data.forward = targetForward;
                    targetUnit = unit.Data.lockTarget;
                    targetList.Clear();
                    targetList.Add(targetUnit);
                }
                else*/
                {
                    StartRecover();
                    RemoveEffect();
                    return;
                }
            }
            //else
            {
                shootCount++;
                unit.Data.needNextShoot = false;
                unit.Transmit(ETransmitType.Shoot);
                if (string.IsNullOrEmpty(config.action_name))
                {
                    unit.Play("Attack");
                }
                else
                {
                    unit.Play(config.action_name);
                }
                startShootTime = currentTime;
                startBulletTime = 0;
                foreach (var item in bullets.Values)
                {
                    for (int i = 0; i < item.Count; i++)
                    {
                        item[i].startTime = currentTime + item[i].bulletConfig.x / 30f / unit.Data.attackSpeedRatio;
                    }
                }
            }
        }

        private void GetRealBulletId(ref int bulletId)
        {
            if (config.change_bullets == null)
            {
                return;
            }
            for (int i = 0; i < config.change_bullets.Count; i++)
            {
                if (config.change_bullets[i].x <= bulletCount && config.change_bullets[i].y >= bulletCount)
                {
                    bulletId = (int)config.change_bullets[i].z;
                    return;
                }
            }
        }

        protected override void UpdateSound(PveSkillConfig config)
        {
            
        }
        
        private void Bullet(Vector3Int bullet,Vector3 effect)
        {
            if (unit.Data.lockTarget == null || unit.Data.lockTarget != lastLockTarget)
            {
                StartRecover();
                RemoveEffect();
                return;
            }
            int bulletId = (int)bullet.y;
            GetRealBulletId(ref bulletId);
            bulletCount++;
            PlayBulletSound();
            var offset = GetBulletOffset((int)bullet.z);
            
            //Debug.LogError(PveManager.frame + "\t" + unit.Data.id + " 近战攻击结算");
            //if (config.director_type == 4 || config.director_type == 0)//向targetList方向
            {
                CreateBulletByTargets(offset,bulletId,0,(int)bullet.z);
            }
            /*else//向自身方向
            {
                CreateBulletByCertainForward(offset,bulletId);
            }*/

            /*var pos = unit.Data.position;
            
            if (effect.y != 0)
            {
                if (unit.Data.gunPoints.Count > bullet.z)
                {
                    pos = unit.Data.gunPoints[(int)bullet.z].position;
                }
                else
                {
                    pos = unit.Data.gunPoints[0].position;
                }
                
                PveEffectManager.Instance.PlayEffect((int)effect.y,pos,unit.Data.forward,effect.z / 30);
            }*/
        }
    }
}